package cn.sylinx.hbatis.io;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import cn.sylinx.hbatis.log.GLog;

/**
 * classloader包装
 * 
 * @author han
 *
 */
public class ClassLoaderWrapper {

	/**
	 * 默认ClassLoader
	 */
	ClassLoader defaultClassLoader;

	/**
	 * 系统ClassLoader
	 */
	ClassLoader systemClassLoader;

	ClassLoaderWrapper() {
		try {
			systemClassLoader = ClassLoader.getSystemClassLoader();
		} catch (SecurityException ignored) {
		}
	}

	/**
	 * 获取URL资源
	 * 
	 * @param resource
	 *            资源
	 * @return URL
	 */
	public URL getResourceAsURL(String resource) {
		return getResourceAsURL(resource, getClassLoaders(null));
	}

	public List<URL> getResourceAsURLs(String resource) {
		return getResourceAsURLs(resource, getClassLoaders(null));
	}

	/**
	 * 获取URL资源
	 * 
	 * @param resource
	 *            资源
	 * @param classLoader
	 *            ClassLoader对象
	 * @return URL
	 */
	public URL getResourceAsURL(String resource, ClassLoader classLoader) {
		return getResourceAsURL(resource, getClassLoaders(classLoader));
	}

	public List<URL> getResourceAsURLs(String resource, ClassLoader classLoader) {
		return getResourceAsURLs(resource, getClassLoaders(classLoader));
	}

	/**
	 * 获取资源输入流
	 * 
	 * @param resource
	 *            资源
	 * @return InputStream
	 */
	public InputStream getResourceAsStream(String resource) {
		return getResourceAsStream(resource, getClassLoaders(null));
	}

	/**
	 * 获取资源输入流
	 * 
	 * @param resource
	 *            资源
	 * @param classLoader
	 *            ClassLoader对象
	 * @return InputStream
	 */
	public InputStream getResourceAsStream(String resource, ClassLoader classLoader) {
		return getResourceAsStream(resource, getClassLoaders(classLoader));
	}

	/**
	 * 加载类
	 * 
	 * @param name
	 *            类名称
	 * @return Class对象
	 * @throws ClassNotFoundException
	 *             类找不到异常
	 */
	public Class<?> classForName(String name) throws ClassNotFoundException {
		return classForName(name, getClassLoaders(null));
	}

	/**
	 * 加载类
	 * 
	 * @param name
	 *            类名称
	 * @param classLoader
	 *            类加载器
	 * @return Class对象
	 * @throws ClassNotFoundException
	 *             类找不到异常
	 */
	public Class<?> classForName(String name, ClassLoader classLoader) throws ClassNotFoundException {
		return classForName(name, getClassLoaders(classLoader));
	}

	/**
	 * 获取资源InputStream
	 * 
	 * @param resource
	 *            资源
	 * @param classLoader
	 *            ClassLoader[]对象
	 * @return InputStream
	 */
	InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
		for (ClassLoader cl : classLoader) {
			if (null != cl) {

				InputStream returnValue = cl.getResourceAsStream(resource);

				if (null == returnValue) {
					returnValue = cl.getResourceAsStream("/" + resource);
				}

				if (null != returnValue) {
					return returnValue;
				}
			}
		}
		return null;
	}

	/**
	 * 获取URL
	 * 
	 * @param resource
	 *            资源
	 * @param classLoader
	 *            类加载器
	 * @return URL
	 */
	URL getResourceAsURL(String resource, ClassLoader[] classLoader) {

		URL url;

		for (ClassLoader cl : classLoader) {

			if (null != cl) {

				url = cl.getResource(resource);

				if (null == url) {
					url = cl.getResource("/" + resource);
				}

				if (null != url) {
					return url;
				}
			}
		}
		return null;
	}

	/**
	 * 获取类路径下所有资源
	 * 
	 * @param resource
	 * @param classLoader
	 * @return
	 */
	List<URL> getResourceAsURLs(String resource, ClassLoader[] classLoader) {

		List<URL> urlList = new ArrayList<>();
		boolean bingo = false;
		
		try {
			for (ClassLoader cl : classLoader) {
				if (null != cl) {
					Enumeration<URL> urlEnums = cl.getResources(resource);
					if (urlEnums != null) {
						while (urlEnums.hasMoreElements()) {
							bingo = true;
							urlList.add(urlEnums.nextElement());
						}
					}
					
					if(bingo) {
						return urlList;
					}
				}
			}
		} catch (IOException e) {
			GLog.error("get resources error", e);
		}

		return urlList;
	}

	/**
	 * 加载类
	 * 
	 * @param name
	 *            类名称
	 * @param classLoader
	 *            类加载器
	 * @return Class对象
	 * @throws ClassNotFoundException
	 *             找不到类异常
	 */
	Class<?> classForName(String name, ClassLoader[] classLoader) throws ClassNotFoundException {

		for (ClassLoader cl : classLoader) {

			if (null != cl) {

				try {

					Class<?> c = Class.forName(name, true, cl);

					if (null != c) {
						return c;
					}

				} catch (ClassNotFoundException e) {
				}

			}

		}

		throw new ClassNotFoundException("Cannot find class: " + name);

	}

	/**
	 * 获取类加载器对象数组
	 * 
	 * @param classLoader
	 *            类加载器
	 * @return ClassLoader[]对象
	 */
	ClassLoader[] getClassLoaders(ClassLoader classLoader) {
		return new ClassLoader[] { classLoader, defaultClassLoader, Thread.currentThread().getContextClassLoader(),
				getClass().getClassLoader(), systemClassLoader };
	}

}
